package com.nemodynamic.cattivial.UIElement;

import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import com.nemodynamic.cattivial.R;
import com.nemodynamic.cattivial.beansElement.CattivialFaceItem;
import com.nemodynamic.cattivial.beansElement.CattivialFoodItem;
import com.nemodynamic.cattivial.utils.DLog;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.media.AudioManager;
import android.media.SoundPool;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.TextView;

public class CattivialFaceItemView extends View {
	private static final String TAG = "CattivialFaceItemView";
	private TextView[] results;
	private List<CattivialFoodItem> foodItems;
	private CattivialFaceItem faceItem;
	private static boolean isStarted = false;
	private boolean isLookedUntilConsumed = false;
	private float speedFactor = 0;
	private float mScaleFactor = 0.2f;
	private float fattenStateFactor = 1.0f;
	private boolean isInit = true;
	private static long score = 0;
	private Paint paintTimer;
	private Paint paintOrder;
	private Bitmap cattivialFaceBitmap;
	private float radius = 0;
	private int time;
	private int foodValue = 1;
	private int changingX = 0;
	private int changingY = 0;
	private int xMove = 0;
	private int yMove = 0;
	private int top = 0;
	private int bottom = 0;
	private int left = 0;
	private int right = 0;
	private int cattivialFaceBitmapWidth = 0;
	private int cattivialFaceBitmapHeight = 0;
	private int orderTextMargin = 0;
	private int timerTextSize = 0;
	private int orderTextSize = 0;
	private boolean isCaptured = false;
	private Timer faceItemtimer;
	private TimerTask faceItemTimerTask;
	private OnCativalFaceItemAction onCativalFaceItemActionListener;
	private AudioManager audioManager;
	private SoundPool soundPool;
	int dragSound;

	public OnCativalFaceItemAction getOnCativalFaceItemActionListener() {
		return onCativalFaceItemActionListener;
	}

	public void setOnCativalFaceItemActionListener(
			OnCativalFaceItemAction onCativalFaceItemActionListener) {
		this.onCativalFaceItemActionListener = onCativalFaceItemActionListener;
	}

	public CattivialFaceItemView(Context context, CattivialFaceItem faceItem,
			Bitmap cattivialFaceBitmap, View parent, TextView[] results,
			float speedFactor, SoundPool soundPool, int dragSound) {

		super(context);
		this.soundPool = soundPool;
		this.dragSound = dragSound;
		this.faceItem = faceItem;
		this.time = faceItem.getMaxTime();
		this.speedFactor = speedFactor;
		this.results = results;
		this.cattivialFaceBitmap = cattivialFaceBitmap;
		cattivialFaceBitmapWidth = cattivialFaceBitmap.getWidth();
		cattivialFaceBitmapHeight = cattivialFaceBitmap.getHeight();
		radius = cattivialFaceBitmapWidth / 5;
		timerTextSize = cattivialFaceBitmapWidth / 2;
		orderTextSize = (int) (radius);
		orderTextMargin = cattivialFaceBitmapWidth / 8;
		paintTimer = new Paint();
		paintTimer.setColor(Color.WHITE);
		xMove = (int) (Math.log(Math.E + foodValue) * Math.sqrt(speedFactor
				+ foodValue));
		yMove = (int) (Math.log(Math.E + foodValue) * Math.sqrt(speedFactor
				+ foodValue));
		paintTimer.setShadowLayer(2.0f, 1.0f, 1.0f, Color.BLACK);
		paintTimer.setAntiAlias(true);
		paintTimer.setTextSize(timerTextSize);
		Typeface tf = Typeface.create("Roboto", Typeface.BOLD);
		paintTimer.setTypeface(tf);
		paintOrder = new Paint();
		paintOrder.setColor(Color.BLACK);
		paintOrder.setShadowLayer(2.0f, 1.0f, 1.0f, Color.DKGRAY);
		paintOrder.setAntiAlias(true);
		paintOrder.setTextSize(orderTextSize);
		paintOrder.setTypeface(tf);
		bottom = parent.getBottom() - cattivialFaceBitmapHeight;
		left = parent.getLeft();
		right = parent.getRight() - cattivialFaceBitmapWidth;
		Random ramdomX = new Random();
		Random ramdomY = new Random();
		changingX = ramdomX.nextInt(right - left) + left;
		changingY = ramdomY.nextInt(bottom - top) + top;
		faceItemtimer = new Timer();
		this.audioManager = (AudioManager) context
				.getSystemService(Context.AUDIO_SERVICE);
		cleanResultSelection();

		faceItemTimerTask = new TimerTask() {

			@Override
			public void run() {
				time--;
				if (time == 0 || isStarted == false) {
					faceItemTimerTask.cancel();
					faceItemtimer.cancel();
					post(new Runnable() {

						@Override
						public void run() {
							Animation itemExpiredAnim = AnimationUtils
									.loadAnimation(getContext(),
											R.anim.item_anim_expired);
							itemExpiredAnim.setInterpolator(getContext(),
									R.anim.item_click_interpolator);
							itemExpiredAnim
									.setAnimationListener(new AnimationListener() {

										@Override
										public void onAnimationStart(
												Animation animation) {
										}

										@Override
										public void onAnimationRepeat(
												Animation animation) {
										}

										@Override
										public void onAnimationEnd(
												Animation animation) {
											setVisibility(View.GONE);
											if (onCativalFaceItemActionListener != null) {
												getFaceItem().setConsumed(true);
												onCativalFaceItemActionListener
														.onItemExpired(CattivialFaceItemView.this);
												cleanResultSelection();
											} else {
												invalidate();
											}

										}
									});
							startAnimation(itemExpiredAnim);

						}
					});
				}
				post(new Runnable() {

					@Override
					public void run() {
						invalidate();
					}
				});

			}
		};

	}

	@Override
	/**
	 * A face is in the init state when is created and before that the game center select the faceItem to be active.
	 * When the faceItem became active the countdown timer start and the state is ACTIVE 
	 */
	public void onDraw(Canvas canvas) {
		if (isStarted) {
			
			if (faceItem.isActive() && isInit) {
				isInit = false;
				
				try {
					DLog.i(TAG, "Attivato il timer per: " + this.getFaceItem());
					faceItemtimer.scheduleAtFixedRate(faceItemTimerTask, 1000,
							1000);
				} catch (Exception e) {
					DLog.e(TAG, "Rosolvere il problema del timer");
				}

			}

			if (!isCaptured) {
				canvas.scale(fattenStateFactor, fattenStateFactor, getWidth()
						/ 2 + radius, getHeight() / 2 + radius);
				drawFaceItem(canvas);
				if (changingX > right || changingX < left) {
					xMove = -xMove;
				}
				if (changingY < top || changingY > bottom) {
					yMove = -yMove;
				}
				if (!isLookedUntilConsumed) {
					changingX = changingX + xMove;
					changingY = changingY + yMove;
				}
			} else {
				canvas.scale(fattenStateFactor + mScaleFactor,
						fattenStateFactor + mScaleFactor, getWidth() / 2
								+ radius, getHeight() / 2 + radius);

				drawFaceItem(canvas);
			}

		}
		invalidate();
		if (!isStarted && !isInit) {
			DLog.i(TAG, "FaceTimerCancelled");
			faceItemTimerTask.cancel();
			faceItemtimer.cancel();
		}
	}

	private void drawFaceItem(Canvas canvas) {
		String timeString = "" + time;
		String orderString = "" + foodValue;
		float wTimer = paintTimer.measureText(timeString, 0,
				timeString.length());
		float wOrder = paintOrder.measureText(orderString, 0,
				orderString.length());
		float xTimerPos = changingX + cattivialFaceBitmapWidth / 2 - wTimer / 2
				- 3;
		float yTimerPos = changingY + cattivialFaceBitmapHeight / 2 + 13;
		float xOrderPos = changingX + orderTextMargin - wOrder / 2;
		float yOrderPos = changingY + radius / 2 + orderTextMargin - 3;

		canvas.drawBitmap(cattivialFaceBitmap, changingX, changingY, null);
		canvas.drawCircle(changingX + orderTextMargin, changingY
				+ orderTextMargin, radius, paintTimer);
		if (faceItem.isActive()) {
			canvas.drawText(timeString, 0, timeString.length(), xTimerPos,
					yTimerPos, paintTimer);
		}
		canvas.drawText(orderString, 0, orderString.length(), xOrderPos,
				yOrderPos, paintOrder);

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {

		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			if (isViewContains((int) event.getX(), (int) event.getY())) {
				// System.out.println(this + "DOWN");
				changingX = (int) event.getX() - cattivialFaceBitmapWidth / 2;
				changingY = (int) event.getY() - cattivialFaceBitmapWidth / 2;
				isCaptured = true;
				return true;
			}
		}
		if (isCaptured) {
			if (event.getAction() == MotionEvent.ACTION_UP) {
				// System.out.println(this + "UP");
				Integer result = null;
				if ((result = isOverSomeResult((int) event.getX(),
						(int) event.getY())) != null) {
					if (result.intValue() == faceItem.getRightResult()) {
						isLookedUntilConsumed = true;
						score += foodValue * time;
						getFaceItem().setConsumed(true);
						cleanResultSelection();
						if (onCativalFaceItemActionListener != null) {
							faceItemtimer.cancel();
							onCativalFaceItemActionListener
									.onCorrectAnswer(CattivialFaceItemView.this);
						}

					} else {
						cleanResultSelection();
						if (onCativalFaceItemActionListener != null) {
							faceItemtimer.cancel();
							getFaceItem().setConsumed(true);
							onCativalFaceItemActionListener
									.onBadAnswer(CattivialFaceItemView.this);
						}
					}
				} else {
					cleanResultSelection();
				}
				isCaptured = false;

				return true;
			}
			if (event.getAction() == MotionEvent.ACTION_MOVE) {
				if(isInit==false){
				DLog.i(TAG, "init False");
				}
				if(!faceItem.isActive()){
					DLog.i(TAG, "NON Attivato il timer per: " + this.getFaceItem() +"isActive False");
				}
				changingX = (int) event.getX() - cattivialFaceBitmapWidth / 2;
				changingY = (int) event.getY() - cattivialFaceBitmapWidth / 2;

				if (isItemOverTheFood(foodItems, (int) event.getX(),
						(int) event.getY())) {
					onCativalFaceItemActionListener
							.onEat(CattivialFaceItemView.this);
				}

				if ((changingX % 5) == 0 || (changingY % 5) == 0) {
					float actualVolume = (float) audioManager
							.getStreamVolume(AudioManager.STREAM_MUSIC);
					float maxVolume = (float) audioManager
							.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
					float volume = actualVolume / maxVolume;
					soundPool.play(dragSound, volume, volume, 1, 0, 1f);
				}

				isOverSomeResult((int) event.getX(), (int) event.getY());
				return true;
			}
		}

		return false;

	}

	private boolean isViewContains(int rx, int ry) {
		int x = changingX;
		int y = changingY;
		int w = cattivialFaceBitmapWidth;
		int h = cattivialFaceBitmapHeight;
		if (rx < x || rx > x + w || ry < y || ry > y + h) {
			return false;
		}
		return true;
	}

	private Integer isOverSomeResult(int x, int y) {
		// System.out.println(x + " " + y);
		int top = ((View) results[0].getParent().getParent()).getTop();
		int left = ((View) results[0].getParent()).getLeft();
		Rect result1 = new Rect(results[0].getLeft() + left,
				results[0].getTop() + top, results[0].getRight() + left,
				results[0].getBottom() + top);
		// System.out.println(result1);
		if (result1.contains(x, y)) {
			//System.out.println("Result1");
			results[0].setBackgroundDrawable((new BitmapDrawable(
					getResources(), cattivialFaceBitmap)));
			results[0].getBackground().setState(SELECTED_STATE_SET);
			results[1].setBackgroundColor(Color.TRANSPARENT);
			results[1].getBackground().setState(ENABLED_STATE_SET);
			results[2].setBackgroundColor(Color.TRANSPARENT);
			results[2].getBackground().setState(ENABLED_STATE_SET);
			return Integer.parseInt((results[0].getText().toString()));
		}
		left = ((View) results[1].getParent()).getLeft();
		Rect result2 = new Rect(results[1].getLeft() + left,
				results[1].getTop() + top, results[1].getRight() + left,
				results[1].getBottom() + top);
		//System.out.println(result2);
		if (result2.contains(x, y)) {
			//System.out.println("Result2");
			results[1].setBackgroundDrawable((new BitmapDrawable(
					getResources(), cattivialFaceBitmap)));
			results[1].getBackground().setState(SELECTED_STATE_SET);
			results[0].setBackgroundColor(Color.TRANSPARENT);
			results[0].getBackground().setState(ENABLED_STATE_SET);
			results[2].setBackgroundColor(Color.TRANSPARENT);
			results[2].getBackground().setState(ENABLED_STATE_SET);
			return Integer.parseInt((results[1].getText().toString()));
		}
		left = ((View) results[2].getParent()).getLeft();
		Rect result3 = new Rect(results[2].getLeft() + left,
				results[2].getTop() + top, results[2].getRight() + left,
				results[2].getBottom() + top);
		//System.out.println(result3);
		if (result3.contains(x, y)) {
			//System.out.println("Result3");
			results[2].setBackgroundDrawable((new BitmapDrawable(
					getResources(), cattivialFaceBitmap)));
			results[2].getBackground().setState(SELECTED_STATE_SET);
			results[1].setBackgroundColor(Color.TRANSPARENT);
			results[1].getBackground().setState(ENABLED_STATE_SET);
			results[0].setBackgroundColor(Color.TRANSPARENT);
			results[0].getBackground().setState(ENABLED_STATE_SET);
			return Integer.parseInt((results[2].getText().toString()));
		}
		cleanResultSelection();
		return null;
	}

	public static long getScore() {
		return score;
	}

	public static void start() {
		isStarted = true;
	}

	public static void stop() {
		isStarted = false;
	}

	public interface OnCativalFaceItemAction {
		public void onCorrectAnswer(View itemView);

		public void onItemExpired(View itemView);

		public void onBadAnswer(View itemView);

		public void onEat(View itemView);
	}

	private boolean isItemOverTheFood(List<CattivialFoodItem> foods, int x,
			int y) {
		if (foods != null) {
			for (CattivialFoodItem cattivialFoodItem : foods) {
				if (!cattivialFoodItem.isConsumed()
						&& !cattivialFoodItem.isEaten()
						&& cattivialFoodItem.isToBeDrawn()) {
					if (x >= (cattivialFoodItem.getX())
							&& x <= (cattivialFoodItem.getX() + cattivialFoodItem
									.getWidth())
							&& y >= (cattivialFoodItem.getY())
							&& y <= (cattivialFoodItem.getY() + cattivialFoodItem
									.getHeight())) {
						cattivialFoodItem.setEaten(true);
						foodValue += cattivialFoodItem.getScore();
						DLog.i(TAG, "Eaten");
						return true;
					}
				}
			}
		}

		return false;

	}

	private void cleanResultSelection() {
		results[0].setBackgroundColor(Color.TRANSPARENT);
		results[1].setBackgroundColor(Color.TRANSPARENT);
		results[2].setBackgroundColor(Color.TRANSPARENT);
		results[0].getBackground().setState(ENABLED_STATE_SET);
		results[1].getBackground().setState(ENABLED_STATE_SET);
		results[2].getBackground().setState(ENABLED_STATE_SET);
	}

	public void setFoods(List<CattivialFoodItem> foodItems) {
		// System.out.println("Food Items set " + foodItems);
		this.foodItems = foodItems;
	}

	public CattivialFaceItem getFaceItem() {
		return faceItem;
	}

}
